package cz.none.bezbarier.web.controller;

import java.util.Locale;

import javax.validation.Valid;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import cz.none.bezbarier.web.form.UserControllForm;
import cz.none.bezbarier.web.form.UserForm;
import cz.none.bezbarier.web.model.Role;
import cz.none.bezbarier.web.model.User;
import cz.none.bezbarier.web.service.UserService;
import cz.none.bezbarier.web.service.exception.ServiceException;
import cz.none.bezbarier.web.util.Constants;
import cz.none.bezbarier.web.vo.FlashMessage.Severity;

@Controller
@RequestMapping(Constants.Page.ADMIN_M)
public class AdminController extends AController {

	private static final Logger LOG = LoggerFactory.getLogger(AdminController.class);

	@Autowired
	private UserService service;

	@PreAuthorize("hasRole('ADMIN')")
	@RequestMapping(Constants.Page.USER_LIST_M)
	public String listUsers(Model model) {
		LOG.info("listUsers() :: start");
		model.addAttribute("users", service.getAllUsers());

		LOG.info("listUsers() :: end");
		return Constants.Page.USER_LIST;
	}

	@PreAuthorize("hasRole('ADMIN')")
	@RequestMapping(value = Constants.Page.USER_ADD_M, method = RequestMethod.GET)
	public String registerUser(Model model,
			@RequestHeader(value = "referer", required = false) final String referer) {
		LOG.info("addUser() :: start");
		UserForm form = new UserForm();
		form.setReferer(referer);
		model.addAttribute("form", form);

		LOG.info("addUser() :: end");
		return Constants.Page.USER_FORM;
	}

	@PreAuthorize("hasRole('ADMIN')")
	@RequestMapping(value = Constants.Page.USER_ADD_M, method = RequestMethod.POST)
	public String submitUserForm(@ModelAttribute("form") @Valid UserForm form, BindingResult result,
			Locale locale, Model model,
			@RequestParam("_submit") final String action) {
		LOG.info("addUser() :: start");

		if (!Constants.Form.SUBMIT.equals(action)) {
			LOG.debug("addUser():: clicked storno");
			return redirectToReferer(form);
		}

		if (result.hasErrors()) {
			LOG.debug("addUser():: form has errors");
			addFlashMessage(model, result, locale);
			return Constants.Page.USER_FORM;
		}

		if (!form.getPassword1().equals(form.getPassword2())) {
			FieldError error = new FieldError("form", "password2", null, false,
					new String[] { "user-form.password.error" }, null, "Passwords must be same");
			result.addError(error);
			addFlashMessage(model, result, locale);
			return Constants.Page.USER_FORM;
		}

		service.registerUser(form);

		LOG.info("addUser() :: end");
		addFlashMessage(model, Severity.INFO, "user-form.success", new Object[] {});
		return redirectToReferer(form);
	}

	@PreAuthorize("hasRole('ADMIN')")
	@RequestMapping(value = Constants.Page.USER_EDIT_M, method = RequestMethod.GET)
	public String editUser(Model model, @PathVariable("userId") String userId,
			@RequestHeader(value = "referer", required = false) final String referer, RedirectAttributes redir) {
		LOG.info("editUser() :: start");
		User user;
		try {
			user = service.find(userId);
		} catch (ServiceException e) {
			addFlashMessage(redir, Severity.ERROR, "catalog.edit.error.bad.id", userId);
			setActiveMenu(redir, Constants.Menu.HOME);
			return redirectToPage(Constants.Page.ADMIN_M);
		}
		UserControllForm form = new UserControllForm();
		form.setReferer(referer);
		form.setActive(user.getActive());
		form.setLocked(user.getLocked());
		form.setRole(user.getRole());
		form.setId(user.getId());

		model.addAttribute("form", form);
		model.addAttribute("useredit", user);
		model.addAttribute("allRoles", Role.values());

		LOG.info("editUser() :: end");
		return Constants.Page.USER_EDIT_FORM;
	}

	@PreAuthorize("hasRole('ADMIN')")
	@RequestMapping(value = Constants.Page.USER_EDIT_M, method = RequestMethod.POST)
	public String submitUserControllForm(@ModelAttribute("form") @Valid UserControllForm form,
			BindingResult result, Locale locale, Model model, @RequestParam("_submit") final String action) {
		LOG.info("submitUserControllForm() :: start");

		if (!Constants.Form.SUBMIT.equals(action)) {
			LOG.debug("submitUserControllForm():: clicked storno");
			return redirectToReferer(form);
		}

		if (result.hasErrors()) {
			LOG.debug("submitUserControllForm():: form has errors");
			addFlashMessage(model, result, locale);
			return Constants.Page.USER_FORM;
		}

		service.updateUser(form);

		LOG.info("submitUserControllForm() :: end");
		addFlashMessage(model, Severity.INFO, "user.edit.success", new Object[] {});
		return redirectToReferer(form);
	}

	@PreAuthorize("hasRole('ADMIN')")
	@RequestMapping(value = Constants.Page.USER_DEL_M)
	public String deleteUser(@PathVariable("userId") String userId, RedirectAttributes model) {

		if (service.deleteUser(userId)) {
			addFlashMessage(model, Severity.INFO, "user-list.delete-success", new Object[] {});
		} else {
			addFlashMessage(model, Severity.ERROR, "user-list.delete-failure", new Object[] {});
		}

		return redirectToPage(Constants.Page.ADMIN_M + Constants.Page.USER_LIST_M);
	}

}
